import { Edge, EdgeView, Node } from '@antv/x6'
import { storeToRefs } from 'pinia'
import { useCanvasParameterStore } from './canvasParameter'
import { canvas } from './canvasInstance'
import { generateUUID } from '@renderer/utils/utils'
import { svgPathProperties } from 'svg-path-properties'
import { edgeOriginColor } from './canvasConst'

//#region 画布

//获取当前视口中心
export const getCenter = () => {
  const { canvasPosition } = useCanvasParameterStore()
  const { width, height } = canvas.options
  const zoom = canvas.zoom()
  const x = canvasPosition.x + width / 2 / zoom
  const y = canvasPosition.y + height / 2 / zoom
  return { x, y }
}

//画布平移添加过渡效果
export const smoothCenterTo = (
  sourceX: number,
  sourceY: number,
  targetX: number,
  targetY: number,
  duration = 800
) => {
  const startTime = performance.now()
  const deltaX = targetX - sourceX
  const deltaY = targetY - sourceY

  function animate(time: number) {
    const elapsed = time - startTime
    const t = Math.min(elapsed / duration, 1) // 归一化进度

    // easeOutQuad 缓动
    // const easing = 1 - Math.pow(1 - t, 2)
    const easing = t

    const newX = sourceX + deltaX * easing
    const newY = sourceY + deltaY * easing

    canvas.centerPoint(newX, newY)

    if (t < 1) {
      requestAnimationFrame(animate)
    }
  }

  requestAnimationFrame(animate)
}

//画布模式的切换
export const changeCanvasMode = (mode: 'select' | 'drag' | 'before') => {
  const { isCanvasNodeInteractive, canvasMode } = storeToRefs(useCanvasParameterStore())

  if (mode === 'select') {
    canvas.disablePanning()
    canvas.enableSelection()
    //开启节点的交互
    isCanvasNodeInteractive.value = true
    canvasMode.value.current = 'select'
  } else if (mode === 'drag') {
    canvas.enablePanning()
    canvas.disableSelection()
    //关闭节点的交互
    isCanvasNodeInteractive.value = false
    canvasMode.value.current = 'drag'
  } else if (mode === 'before') {
    changeCanvasMode(canvasMode.value.before)
  }
}

//画布点击时，判断是否有其他事件正在进行
export const isCanvasClick = (): boolean => {
  return false
}

//点击画布时关闭某些工具
export const closeCanvasTools = () => {
  const { isEdgeEdit, isFreeAreaEdit, addEdgeNode } = storeToRefs(useCanvasParameterStore())

  if (isEdgeEdit.value) {
    finishEdgeEdit()
  }
  if (isFreeAreaEdit.value) {
    finishFreeAreaEdit()
  }

  if (addEdgeNode.value.source) {
    canvas.removeCell(addEdgeNode.value.source)
    addEdgeNode.value.source = null
  }
  if (addEdgeNode.value.target) {
    canvas.removeCell(addEdgeNode.value.target)
    addEdgeNode.value.target = null
  }
}

//画布完成编辑处理
export const canvasCompleteEdit = () => {
  const { isEdgeEdit, isFreeAreaEdit } = useCanvasParameterStore()
  if (isEdgeEdit) {
    finishEdgeEdit()
  } else if (isFreeAreaEdit) {
    finishFreeAreaEdit()
  }
}

//#region 节点

//给节点设置连接桩
export const setNodePort = (node: Node) => {
  const type = node.getData()?.type

  //================= output =====================
  if (['produce'].includes(type)) {
    node.addPort({
      group: 'topOut'
    })
  }
  if (['produce', 'process', 'batchProcess', 'assembly', 'disassemble'].includes(type)) {
    node.addPort({
      group: 'bottomOut'
    })
  }
  if (['produce'].includes(type)) {
    node.addPort({
      group: 'leftOut'
    })
  }
  if (['produce', 'process', 'batchProcess', 'assembly', 'disassemble'].includes(type)) {
    node.addPort({
      group: 'rightOut'
    })
  }

  //================= Input =====================

  if (['absorb', 'process', 'batchProcess', 'assembly', 'disassemble'].includes(type)) {
    node.addPort({
      group: 'topIn'
    })
  }
  if (['absorb'].includes(type)) {
    node.addPort({
      group: 'bottomIn'
    })
  }
  if (['absorb', 'process', 'batchProcess', 'assembly', 'disassemble'].includes(type)) {
    node.addPort({
      group: 'leftIn'
    })
  }
  if (['absorb'].includes(type)) {
    node.addPort({
      group: 'rightIn'
    })
  }

  //================= Twoway =====================

  if (['buffer', 'crossing'].includes(type)) {
    node.addPort({
      group: 'topTwoway'
    })
  }
  if (['buffer', 'crossing'].includes(type)) {
    node.addPort({
      group: 'bottomTwoway'
    })
  }
  if (['buffer', 'crossing'].includes(type)) {
    node.addPort({
      group: 'leftTwoway'
    })
  }
  if (['buffer', 'crossing'].includes(type)) {
    node.addPort({
      group: 'rightTwoway'
    })
  }
}

//判断连接桩的类型
export const getPortType = (ports: any[], position: 'top' | 'bottom' | 'left' | 'right') => {
  const port = ports.find((item) => item.group.includes(position))
  if (!port) {
    return { id: '', type: 'none' }
  }
  if (port.group.includes('In')) {
    return { id: port.id, type: 'input' }
  } else if (port.group.includes('Out')) {
    return { id: port.id, type: 'output' }
  } else if (port.group.includes('Twoway')) {
    return { id: port.id, type: 'twoway' }
  } else {
    return { id: '', type: 'none' }
  }
}

//连接桩的显示和隐藏
export const setPortVisible = (mark: boolean) => {
  const nodes = canvas.getNodes()
  nodes.forEach((node) => {
    if (
      ['produce', 'absorb', 'buffer', 'process', 'assembly', 'disassemble'].includes(
        node.getData()?.type
      )
    ) {
      const ports = node.getPorts()
      ports.forEach((port) => {
        node.setPortProp(
          port.id || '',
          'attrs/portBody/style/visibility',
          mark ? 'visible' : 'hidden'
        )
      })
    }
  })
}

//节点粘贴
export const pasteNode = () => {
  const { copyNodeList } = storeToRefs(useCanvasParameterStore())
  const originalNode = [] as any[]
  copyNodeList.value.forEach((id) => {
    const result = window.api.handleCanvasData('getNodes', 'canvas2D', false, ['id', id])
    originalNode.push(result[0])
  })
  const newNode = [] as any[]

  originalNode.forEach((node) => {
    const tempNode = JSON.parse(JSON.stringify(node))
    tempNode.id = generateUUID()
    tempNode.x += 20
    tempNode.y += 20
    newNode.push(tempNode)
  })
  window.api.handleCanvasData('addNodes', 'canvas2D', true, [newNode])
}

//整理节点的simData
export const arrangeSimData = (node: Node): any => {
  const type = node.getData()?.type
  let temp = {}
  if (type === 'produce') {
    temp = {
      product: {
        width: 20,
        height: 20,
        backgroundColor: '#ffbbbbb0',
        borderRadius: 0,
        borderWidth: 1,
        borderColor: '#b81e1eb6'
      },
      produce: {
        quantity: 2,
        interval: {
          type: 'fixed',
          fixed: 3,
          random: ''
        },
        selfCirculation: true
      }
    }
  } else if (type === 'process') {
    temp = {
      process: {
        processTime: {
          type: 'fixed',
          fixed: 10,
          random: ''
        },
        defectiveRate: 0,
        failureRate: 0,
        enablePorts: false,
        loaderPoints: [0, 0],
        cuttingPoints: [0, 0],
        personAssist: false
      }
    }
  } else if (type === 'batchProcess') {
    temp = {
      batchProcess: {
        batchQuantity: 10,
        processTime: 10,
        animationDirection: 'left'
      }
    }
  } else if (type === 'buffer') {
    temp = {
      buffer: {
        capacity: 5
      }
    }
  } else if (type === 'assembly') {
    temp = {
      product: {
        width: 20,
        height: 20,
        backgroundColor: '#ffbbbbb0',
        borderRadius: 0,
        borderWidth: 1,
        borderColor: '#b81e1eb6'
      },
      assemble: {
        assembleTime: 5,
        inputPorts: {},
        inputPortsVisual: []
      }
    }
  } else if (type === 'disassemble') {
    temp = {
      product: {
        width: 20,
        height: 20,
        backgroundColor: '#ffbbbbb0',
        borderRadius: 0,
        borderWidth: 1,
        borderColor: '#b81e1eb6'
      },
      disassemble: {
        disassembleTime: 5,
        quantity: 2
      }
    }
  } else if (type === 'AGV') {
    temp = {
      agv: {
        speed: 50,
        capacity: 1,
        rotateSpeed: 90,
        loadTime: 0,
        unloadTime: 0,
        enableTraffic: false
      }
    }
  } else if (type === 'workerPool') {
    temp = {
      workerPool: {
        workerNum: 20,
        workerSpeed: 100,
        maintenanceTime: 5,
        associatedDevices: []
      }
    }
  } else if (type === 'plaintext') {
    temp = {
      plaintext: {
        text: '自定义文字',
        fill: '#4E5969',
        fontSize: 15,
        fontWeight: 'regular',
        letterSpacing: 0
      }
    }
  }

  return temp
}

//给节点左上角添加数字
export const addNumberToNode = (addNode: Node, data: any) => {
  /**
   * 需要在左上角显示数字的节点
   */
  const displayNumberNode = [
    {
      type: 'produce',
      field: 'quantity'
    },
    {
      type: 'batchProcess',
      field: 'batchQuantity'
    },
    {
      type: 'buffer',
      field: 'capacity'
    },
    {
      type: 'workerPool',
      field: 'workerNum'
    }
  ]
  const index = displayNumberNode.findIndex((item) => item.type === data.type)
  if (index !== -1) {
    addNode.setData({
      quantity: data.simData[displayNumberNode[index].type][displayNumberNode[index].field]
    })
  }
}

//自由编辑区域双击时，显示编辑的顶点
export const showVertex = (node: Node) => {
  if (node.shape !== 'custom-port-node') return
  const { isFreeAreaEdit } = storeToRefs(useCanvasParameterStore())
  isFreeAreaEdit.value = true

  const position = node.getPosition()
  const refPoints = node.getAttrByPath('body/points') as string
  const vertex = refPointsToPoints(refPoints)

  const nodes = [] as Node[]
  vertex.forEach((item, index) => {
    const x = position.x + item.x
    const y = position.y + item.y
    const node = canvas.addNode({
      shape: 'free-edit-circle',
      x: x - 3,
      y: y - 3
    })
    nodes.push(node)
  })

  nodes.forEach((el, index) => {
    if (index === 0) {
      canvas.addEdge({
        shape: 'free-edit-edge',
        source: nodes[nodes.length - 1].id,
        target: el.id
      })
    } else {
      canvas.addEdge({
        shape: 'free-edit-edge',
        source: nodes[index - 1].id,
        target: el.id
      })
    }
  })

  const { selectedNode } = storeToRefs(useCanvasParameterStore())
  selectedNode.value = node
}

//自由编辑节点移动结束后，更新顶点位置
export const updateVertex = (node: Node) => {
  if (node.shape !== 'free-edit-circle') return
  //先判断两个自由编辑节点是否重合
  const { x, y } = node.getPosition()
  const pointNodes = canvas.getNodesInArea(x - 4, y - 4, 8, 8)
  const freeEditNodes = pointNodes.filter(
    (item) => item.shape === 'free-edit-circle' && item.id !== node.id
  )
  if (freeEditNodes.length > 0) {
    //找到了一个自由编辑节点
    const freeEditNode = freeEditNodes[0]
    const otherInputEdges = canvas.getIncomingEdges(freeEditNode) ?? []
    const otherOutputEdges = canvas.getOutgoingEdges(freeEditNode) ?? []
    const otherEdges = [...otherInputEdges, ...otherOutputEdges]
    const otherEdgesIds = otherEdges.map((item) => item.id)

    //找到node相连的边
    const selfinputEdges = canvas.getIncomingEdges(node) ?? []
    const selfoutputEdges = canvas.getOutgoingEdges(node) ?? []
    const selfEdges = [...selfinputEdges, ...selfoutputEdges]
    const selfEdgesIds = selfEdges.map((item) => item.id)

    //找是否有相同的边
    const sameEdges = otherEdgesIds.filter((item) => selfEdgesIds.includes(item))
    if (sameEdges.length > 0) {
      //找剩余的边
      const remainingEdges = selfEdges.filter((item) => !sameEdges.includes(item.id))
      //转移剩余边的连接关系
      remainingEdges.forEach((item) => {
        if (item.getSourceCellId() === node.id) {
          item.setSource(freeEditNode)
        } else {
          item.setTarget(freeEditNode)
        }
      })

      //删除相同的边
      sameEdges.forEach((item) => {
        canvas.removeEdge(item)
      })

      //删除node
      canvas.removeNode(node)
    }
  }

  //更新自由编辑区域顶点位置
  const { selectedNode } = storeToRefs(useCanvasParameterStore())
  const { x: absoluteX, y: absoluteY } = selectedNode.value!.getPosition()
  //获取画布中所有的自由编辑节点
  const freeEditNodes2 = [node]
  //找到node后续的所有节点
  const successors = (canvas.getSuccessors(node) as Node[]) ?? []
  freeEditNodes2.push(...successors)

  let points = ''
  freeEditNodes2.forEach((item) => {
    const { x, y } = item.getPosition()
    points += `${x + 3 - absoluteX},${y + 3 - absoluteY} `
  })
  selectedNode.value?.attr('body/points', points)
}

//完成自由编辑，删除所有自由编辑节点和边
export const finishFreeAreaEdit = () => {
  const { isFreeAreaEdit, selectedNode } = storeToRefs(useCanvasParameterStore())
  isFreeAreaEdit.value = false
  const points = selectedNode.value?.getAttrByPath('body/points') as string
  const nodeData = window.api.handleCanvasData('getNodes', 'canvas2D', false, [
    'id',
    selectedNode.value!.id!
  ])
  const node = nodeData[0]
  node.points = points
  window.api.handleCanvasData('updateNodes', 'canvas2D', false, [node])

  const freeEditNodes = canvas.getNodes().filter((item) => item.shape === 'free-edit-circle')
  const freeEditEdges = canvas.getEdges().filter((item) => item.shape === 'free-edit-edge')
  canvas.removeCells([...freeEditNodes, ...freeEditEdges])
}

//自由编辑区域节点移动结束
export const freeAreaNodeMoveEnd = (node: Node) => {
  if (node.shape !== 'custom-port-node') return
  const { isFreeAreaEdit } = storeToRefs(useCanvasParameterStore())
  if (isFreeAreaEdit.value) {
    finishFreeAreaEdit()
    showVertex(node)
  }
}

//#region 边

//给边添加工具
export const addEdgeTool = (edge: Edge) => {
  if (['road-edge', 'conveyor-belt', 'warning-line'].includes(edge.shape)) {
    const { isEdgeEdit } = storeToRefs(useCanvasParameterStore())
    if (isEdgeEdit.value) {
      console.log('已处于编辑状态')
      return
    }
    /**
     * 添加路径点工具，线段工具，起始点编辑工具
     */
    edge.addTools([
      {
        name: 'vertices',
        args: {
          attrs: {
            'stroke-width': 1,
            stroke: '#fe854f',
            fill: '#EFF4FF'
          }
        }
      },
      {
        name: 'segments',
        args: {
          attrs: {
            'stroke-width': 1,
            stroke: '#fe854f',
            fill: '#EFF4FF'
          }
        }
      },
      {
        name: 'source-arrowhead',
        args: {
          tagName: 'path',
          attrs: {
            d: 'M -5 -5 L 5 -5 L 5 5 L -5 5 L -5 -5 ',
            fill: '#EFF4FF',
            'stroke-width': 1,
            stroke: '#fe854f'
          }
        }
      },
      {
        name: 'target-arrowhead',
        args: {
          tagName: 'path',
          attrs: {
            d: 'M -5 -5 L 5 -5 L 5 5 L -5 5 L -5 -5 ',
            fill: '#EFF4FF',
            'stroke-width': 1,
            stroke: '#fe854f'
          }
        }
      }
    ])
    isEdgeEdit.value = true
  }
}

//完成边的编辑状态
export const finishEdgeEdit = () => {
  const { isEdgeEdit, selectedEdge } = storeToRefs(useCanvasParameterStore())
  if (!selectedEdge.value) return
  selectedEdge.value?.removeTools()
  isEdgeEdit.value = false

  const beltView = canvas.findViewByCell(selectedEdge.value) as EdgeView
  if (beltView) {
    const path = beltView.getConnectionPathData()

    const edges = window.api.handleCanvasData('getEdges', 'canvas2D', false, [
      'id',
      selectedEdge!.value!.id
    ])
    const edge = edges[0]
    edge.sourceId = selectedEdge.value.getSource() as { x: number; y: number }
    edge.targetId = selectedEdge.value.getTarget() as { x: number; y: number }
    edge.vertices = selectedEdge.value!.getVertices()
    if (edge.simData) {
      edge.simData.path = path
    }
    window.api.handleCanvasData('updateEdges', 'canvas2D', true, [edge])
  }
}

//连接边选中和取消选中，颜色的切换
export const changeEdgeSelect = (edge: Edge | null) => {
  const { selectedEdge } = storeToRefs(useCanvasParameterStore())
  if (selectedEdge.value) {
    const originColor = edgeOriginColor[selectedEdge.value.shape]
    selectedEdge.value.setAttrByPath('p1/stroke', originColor)
  }

  if (!edge) {
    selectedEdge.value = null
    return
  }
  selectedEdge.value = edge
  //获取当前选择的样式
  const canvasProperties = window.api.handleCanvasData('getCanvasProperties', 'canvas2D', false, [])
  const color = canvasProperties.selectedNodeStyleColor
  edge.setAttrByPath('p1/stroke', color)
}

/**
 * 获取 SVG 路径上指定相对位置的坐标和角度
 * @param path SVG path 字符串
 * @param t 相对位置 (0 ~ 1)，如 0.33 表示 33%
 * @returns 坐标点 { x, y } 和角度 angle（单位：度）
 */
export function getPointAndAngleAt(
  path: string,
  t: number
): {
  x: number
  y: number
  angle: number
} {
  if (t < 0 || t > 1) {
    throw new Error('参数 t 必须在 0 到 1 之间')
  }

  const properties = new svgPathProperties(path)
  const totalLength = properties.getTotalLength()

  // 获取指定位置的坐标点
  const point = properties.getPointAtLength(totalLength * t)

  // 获取指定位置的切线方向
  const tangent = properties.getTangentAtLength(totalLength * t)
  const angle = Math.atan2(tangent.y, tangent.x) * (180 / Math.PI) // 转换为角度

  return {
    x: point.x,
    y: point.y,
    angle
  }
}

//特殊边点击事件，给两端附加添加add组件
export const specialEdgeClick = (edge: Edge) => {
  const { isShiftEDown, addEdgeNode } = storeToRefs(useCanvasParameterStore())
  if (!isShiftEDown.value) return
  if (addEdgeNode.value.source) {
    canvas.removeCell(addEdgeNode.value.source)
  }
  if (addEdgeNode.value.target) {
    canvas.removeCell(addEdgeNode.value.target)
  }
  //获取起点和终点
  const target = edge.getTarget()
  const { x: x2, y: y2 } = target as any
  const edgeDataList = window.api.handleCanvasData('getEdges', 'canvas2D', false, ['id', edge.id])
  const edgeData = edgeDataList[0]

  //获取开始方向和结束方向
  const endDirection = getPointAndAngleAt(edgeData.simData!.path!, 1).angle

  const endPosition = calculateTargetPosition({ x: x2, y: y2 }, endDirection, -11)

  const targetNode = canvas.addNode({
    shape: 'add-node',
    x: endPosition.x,
    y: endPosition.y,
    data: {
      type: 'target',
      direction: endDirection
    }
  })
  addEdgeNode.value.target = targetNode
}

//开启边移动
export const openEdgeMove = (edge: Edge) => {
  const { isEdgeMovable } = storeToRefs(useCanvasParameterStore())

  if (['conveyor-belt', 'road-edge', 'warning-line'].includes(edge.shape)) {
    isEdgeMovable.value = true
  }
}

//关闭边移动
export const closeEdgeMove = (edge: Edge) => {
  const { isEdgeMovable } = storeToRefs(useCanvasParameterStore())
  isEdgeMovable.value = false
}

//渲染进程-如果source为特殊节点
export const changeEdgeSourceAnchorPoints = (data: any) => {
  const { selectedEdge, addEdgeNode } = storeToRefs(useCanvasParameterStore())

  if (addEdgeNode.value.target && selectedEdge.value) {
    data.sourceId = selectedEdge.value.id
  }
}

//主进程-如过target为特殊边，则修改边的描点
export const changeEdgeAnchorPoints = (data: any) => {
  const edge = canvas.getCellById(data.id) as Edge
  const sourceCell = canvas.getCellById(data.sourceId)
  if (sourceCell) {
    if (canvas.isEdge(sourceCell)) {
      edge.prop('source/anchor', {
        name: 'ratio',
        args: {
          ratio: 1
        }
      })
    }
  }
  const targetCell = canvas.getCellById(data.targetId)
  if (targetCell) {
    if (canvas.isEdge(targetCell)) {
      edge.prop('target/anchor', {
        name: 'ratio',
        args: {
          ratio: 0
        }
      })
    }
  }
}

//自由编辑边点击时，添加一个自由编辑的原点
export const addFreeEditCircle = (edge: Edge, x: number, y: number) => {
  if (edge.shape !== 'free-edit-edge') {
    return
  }

  // 创建一个圆形节点
  const circle = canvas.addNode({
    shape: 'free-edit-circle',
    x,
    y
  })
  //获取source
  const sourceId = edge.getSourceCellId()
  canvas.addEdge({
    shape: 'free-edit-edge',
    source: sourceId,
    target: circle.id
  })

  //获取target
  const targetId = edge.getTargetCellId()
  canvas.addEdge({
    shape: 'free-edit-edge',
    source: circle.id,
    target: targetId
  })

  // 移除原始边
  canvas.removeCell(edge)
}

// #region其他
/**
 * 计算从给定点沿指定角度移动固定距离后的新坐标
 * @param origin 起始坐标点 { x: number, y: number }
 * @param angle 移动角度（度数），0度表示正右方，90度表示正下方
 * @param distance 移动距离（像素），默认为15px
 * @returns 新的坐标点 { x: number, y: number }
 */
function calculateTargetPosition(
  origin: { x: number; y: number },
  angle: number,
  distance: number = 15
): { x: number; y: number } {
  // 将角度转换为弧度（网页坐标系中0度指向正右方）
  const radians = (angle * Math.PI) / 180

  // 计算偏移量（注意：y分量需要取负值，因为网页坐标系y轴向下为正）
  const dx = distance * Math.cos(radians)
  const dy = distance * Math.sin(radians) // 取负值以适应网页坐标系

  // 计算新坐标
  return {
    x: origin.x + dx,
    y: origin.y + dy
  }
}

//检测名称是否重复,并返回不重复的名称
export const checkName = (name: string) => {
  const canvas = window.api.handleCanvasData('getCanvas', 'canvas2D', false, [])
  const names = new Set<string>()
  canvas.nodes.forEach((node) => {
    names.add(node.name)
  })
  canvas.edges.forEach((edge) => {
    names.add(edge.name)
  })

  let index = 1
  let newName = name
  while (names.has(newName)) {
    index++
    newName = name + ' ' + index
  }

  if (index === 1) {
    return name
  } else {
    return newName
  }
}

//refPoints 转成 {x:number, y:number}[]
export const refPointsToPoints = (refPoints: any): { x: number; y: number }[] => {
  let refPointsArr = refPoints.split(' ')
  //删除空字符串的元素
  refPointsArr = refPointsArr.filter((item) => item !== '')
  const vertex = refPointsArr.map((item) => {
    const [x, y] = item.split(',')
    return { x: Number(x), y: Number(y) }
  })
  return vertex
}
